package com.gitee.qdbp.jdbc.plugins.impl;

import java.util.Arrays;
import java.util.Map;
import java.util.Properties;
import com.gitee.qdbp.jdbc.plugins.JdbcDataTypeResolver;
import com.gitee.qdbp.tools.utils.ConvertTools;
import com.gitee.qdbp.tools.utils.PropertyTools;

/**
 * 从配置文件中读取转换关系的JdbcDataTypeResolver<br>
 * 默认配置文件: settings/qdbc/qdbc.datatype.txt
 *
 * @author zhaohuihua
 * @version 20210430
 */
public class ConfigableJdbcDataTypeResolver implements JdbcDataTypeResolver {

    // dataType 是数据库原生类型, 如@Column(columnDefinition="TIMESTAMP(3)")
    // jdbcType 是java.sql.Types的字段名

    private final Properties properties;
    // key=jdbcType
    private Map<String, ?> supportDefinePrecisionMaps;
    private Map<String, ?> supportDefineScaleMaps;
    private Map<String, ?> supportDefineLengthMaps;
    private Map<String, ?> supportUnicodeMaps;
    private final SimpleJdbcDataTypeResolver defaults;

    /**
     * 构造函数
     * 
     * @param path 配置文件路径, 如: settings/qdbc/qdbc.datatype.txt
     */
    public ConfigableJdbcDataTypeResolver(String path) {
        this(PropertyTools.load(path, PropertyTools.DEFAULT_CHARSET, ConfigableJdbcDataTypeResolver.class));
    }

    /**
     * 构造函数
     * 
     * @param properties 转换关系配置文件
     */
    public ConfigableJdbcDataTypeResolver(Properties properties) {
        this.properties = properties;
        this.defaults = new SimpleJdbcDataTypeResolver();
        if (properties != null) {
            { // supportDefinePrecision
                String key = "supportDefinePrecision.jdbcTypes";
                String[] values = PropertyTools.getArray(properties, key, false);
                if (values != null && values.length > 0) {
                    this.supportDefinePrecisionMaps = ConvertTools.toMap(Arrays.asList(values));
                }
            }
            { // supportDefineScale
                String key = "supportDefineScale.jdbcTypes";
                String[] values = PropertyTools.getArray(properties, key, false);
                if (values != null && values.length > 0) {
                    this.supportDefineScaleMaps = ConvertTools.toMap(Arrays.asList(values));
                }
            }
            { // supportDefineLength
                String key = "supportDefineLength.jdbcTypes";
                String[] values = PropertyTools.getArray(properties, key, false);
                if (values != null && values.length > 0) {
                    this.supportDefineLengthMaps = ConvertTools.toMap(Arrays.asList(values));
                }
            }
            { // supportUnicode
                String key = "supportUnicode.jdbcTypes";
                String[] values = PropertyTools.getArray(properties, key, false);
                if (values != null && values.length > 0) {
                    this.supportUnicodeMaps = ConvertTools.toMap(Arrays.asList(values));
                }
            }
        }
    }

    public Properties getProperties() {
        return properties;
    }

    @Override
    public Integer parseDataType(String dataType) {
        String jdbcType = dataType;
        if (properties != null && properties.containsKey(dataType)) {
            jdbcType = properties.getProperty(dataType);
        }
        return JdbcDataTypeCache.getJdbcType(jdbcType);
    }

    @Override
    public String getJdbcType(String dataType) {
        String jdbcType = dataType;
        if (properties != null && properties.containsKey(dataType)) {
            jdbcType = properties.getProperty(dataType);
        }
        return jdbcType;
    }

    @Override
    public boolean supportDefinePrecision(String dataType) {
        String jdbcType = getJdbcType(dataType);
        return doSupportDefinePrecision(jdbcType) || doSupportDefineScale(jdbcType);
    }

    @Override
    public boolean supportDefineScale(String dataType) {
        String jdbcType = getJdbcType(dataType);
        return doSupportDefineScale(jdbcType);
    }

    private boolean doSupportDefinePrecision(String dataType) {
        String jdbcType = getJdbcType(dataType);
        if (supportDefinePrecisionMaps == null || supportDefinePrecisionMaps.isEmpty()) {
            return this.defaults.supportDefinePrecision(dataType);
        } else {
            return supportDefinePrecisionMaps.containsKey(jdbcType);
        }
    }

    private boolean doSupportDefineScale(String dataType) {
        String jdbcType = getJdbcType(dataType);
        if (supportDefineScaleMaps == null || supportDefineScaleMaps.isEmpty()) {
            return this.defaults.supportDefineScale(dataType);
        } else {
            return supportDefineScaleMaps.containsKey(jdbcType);
        }
    }

    @Override
    public boolean supportDefineLength(String dataType) {
        String jdbcType = getJdbcType(dataType);
        if (supportDefineLengthMaps == null || supportDefineLengthMaps.isEmpty()) {
            return this.defaults.supportDefineLength(dataType);
        } else {
            return supportDefineLengthMaps.containsKey(jdbcType);
        }
    }

    @Override
    public boolean supportUnicode(String dataType) {
        String jdbcType = getJdbcType(dataType);
        if (supportUnicodeMaps == null || supportUnicodeMaps.isEmpty()) {
            return this.defaults.supportUnicode(jdbcType);
        } else {
            return supportUnicodeMaps.containsKey(jdbcType);
        }
    }
}
